package com.example.everying.service.statistics.impl;/*
 * 项目名称: everything
 * 文件名: UserRetentionStatsServiceImpl
 * 作者: 张泽阳
 * 日期: 2025/7/8
 * 描述:
 */

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.everying.mapper.statistics.UserRetentionStatsMapper;
import com.example.everying.model.entity.statistics.UserRetentionStats;
import com.example.everying.service.statistics.UserRetentionStatsService;
import com.example.everying.service.statistics.UserSessionService;
import com.example.everying.service.user.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class UserRetentionStatsServiceImpl extends ServiceImpl<UserRetentionStatsMapper, UserRetentionStats> implements UserRetentionStatsService {

    @Autowired
    private UserService userService;

    @Autowired
    private UserSessionService userSessionService;


    /**
     * 计算并保存每日用户留存数据
     *
     * @param cohortDate
     * @param statDate
     */
    @Override
    public void calculateAndSaveRetentionStats(LocalDate cohortDate, LocalDate statDate) {
        // 获取群组日期的用户集合
        List<String> cohortUsers = userService.getNewUserByDate(cohortDate);
        if (cohortUsers == null || cohortUsers.isEmpty()){
            return;
        }
        // 获取统计日期活跃用户集合
        List<String> retentionUsers = userSessionService.getDistinctUsersByDate(statDate);
        if (retentionUsers == null || retentionUsers.isEmpty()){
            return;
        }

        // 计算留存用户
        Set<String> intersection = new HashSet<>(cohortUsers);
        intersection.retainAll(retentionUsers);

        double retentionRate = cohortUsers.isEmpty() ? 0.0 : (double) intersection.size() / cohortUsers.size();

        // 计算天数差
        long dayAfter = ChronoUnit.DAYS.between(cohortDate, statDate);

        UserRetentionStats retentionStats = new UserRetentionStats();
        retentionStats.setCohortDate(cohortDate);
        retentionStats.setStatDate(statDate);
        retentionStats.setDaysAfter((int) dayAfter);
        retentionStats.setCohortUsers(cohortUsers.size());
        retentionStats.setRetainedUsers(intersection.size());
        retentionStats.setRetentionRate(BigDecimal.valueOf(retentionRate));
        retentionStats.setCreateTime(LocalDateTime.now());
        retentionStats.setUpdateTime(LocalDateTime.now());
        save(retentionStats);

    }

    /**
     * 计算指定日期范围内所有可能的留存组合
     *
     * @param startDate
     * @param endDate
     */
    @Override
    public void calculateRetentionForDateRange(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> dates = startDate.datesUntil(endDate.plusDays(1))
                .collect(Collectors.toList());

        // 计算所有日期组合的留存
        for (int i = 0; i < dates.size();  i++) {
            LocalDate cohortDate = dates.get(i);
            if (userService.getNewUserByDate(cohortDate) == null || userService.getNewUserByDate(cohortDate).isEmpty()){
                continue;
            }
            for (int j = i; j < dates.size();  j++) {
                LocalDate statDate = dates.get(j);
                System.out.println("chortdaate:" + cohortDate + "statedate:" + statDate);
                calculateAndSaveRetentionStats(cohortDate, statDate);
            }
        }
    }
}
